//
// Created by csp18 on 2025/2/26.
//

#include "NetAdapter.h"

#include <stdio.h>

#ifdef LINUX
#include <arpa/inet.h>
#else

#include <winsock2.h>

#endif

#include "INetListener.h"

std::vector<INetListener *> NetAdapter::listeners_;

NetAdapter::NetAdapter()
{

}

string NetAdapter::NetDevsList()
{

    string str = "error";

    pcap_if_t *currDev; //当前设备信息
    char errbuf[PCAP_ERRBUF_SIZE];  //保存设备信息

    /* 获取本地设备列表 */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL,
                            &allDevs, errbuf) == -1)
    {
        fprintf(stderr,
                "Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
    }

    /* 遍历设备列表 */
    int index = 1;
    for (currDev = allDevs; currDev != NULL; currDev = currDev->next)
    {
        printf("%d. DevName : %s\n", index++, currDev->name);

        if (currDev->description)
        {
            printf("Description (%s)\n", currDev->description);
        } else
        {
            printf(" (No Description Available)\n");
        }

        //遍历 IP 设备地址
        pcap_addr_t *addr;
        for (addr = currDev->addresses; addr != NULL; addr = addr->next)
        {
            if (addr->addr && addr->addr->sa_family == AF_INET)
            {
                struct sockaddr_in *ip_addr = (struct sockaddr_in *) addr->addr;
                struct sockaddr_in *net_mask = (struct sockaddr_in *) addr->netmask;

                printf("IP Address : %s\n", inet_ntoa(ip_addr->sin_addr));
                if (net_mask)
                {
                    printf("Subnet Mask : %s\n", inet_ntoa(net_mask->sin_addr));
                }
            }
        }
    }

    if (index == 0)
    {
        printf("\nNo interfaces found! Make sure Npcap is installed.\n");
        //return;
    }

    /* 释放设备列表内存 */
    pcap_freealldevs(allDevs);

    return str;
}

bool NetAdapter::openDev(const char *name)
{

    bool ret = false;
    char errbuf[PCAP_ERRBUF_SIZE];

    //获取网卡(NCID)信息
    pcap_if_t *device = device_find(NCID);
    if (device == NULL)
    {
        fprintf(stderr, "No device found\n");
        return ret;
    }

    //打开设备
    handle = pcap_open_live(device->name, 65535, 1, 1000, errbuf);
    if (!handle)
    {
        fprintf(stderr, "Unable to open device: %s\n", errbuf);
        pcap_freealldevs(allDevs);
        return ret;
    }

    ret = true;
    return ret;
}

void NetAdapter::readDev()
{

    pcap_loop(handle, 1, Notify, NULL);
}

pcap_if_t *NetAdapter::device_find(const char *name)
{

    pcap_if_t *currDev; //当前设备信息
    char errbuf[PCAP_ERRBUF_SIZE];  //保存设备信息
    char nbuf[64];

    sprintf(nbuf, "rpcap://\\Device\\NPF_{%s}", name);

    /* 获取本地设备列表 */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL,
                            &allDevs, errbuf) == -1)
    {
        fprintf(stderr,
                "Error in pcap_findalldevs: %s\n", errbuf);

        return NULL;
    }

    //遍历设备列表
    for (currDev = allDevs; currDev != NULL; currDev = currDev->next)
    {
        if (!strcmp(currDev->name, nbuf))
        {
            return currDev;
        }
    }

    //释放设备列表内存
    pcap_freealldevs(allDevs);
    return NULL;
}

void NetAdapter::Notify(unsigned char *user, const struct pcap_pkthdr *header, const unsigned char *pkt_data)
{
    //std::lock_guard<std::mutex> lock(mtx_);
    for (auto *listener: listeners_)
    {
        listener->on_data_available(user, header, pkt_data);
    }
}

void NetAdapter::addListener(INetListener *listener)
{

    //std::lock_guard<std::mutex> lock(mtx_);
    listeners_.push_back(listener);
}

void NetAdapter::removeListener(INetListener *listener)
{

    //std::lock_guard<std::mutex> lock(mtx_);
    //listeners_.erase(std::remove(listeners_.begin(), listeners_.end(), listener), listeners_.end());
}

void NetAdapter::run()
{
    int i = 100;
    while (i--)
    {
//        readDev();

        pcap_loop(handle, -1, (pcap_handler) &Notify, NULL);
    }
}
